package com.bestcem.xm.ticket.grpc.client;

import cn.hutool.core.lang.ObjectId;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONValidator;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.qdes.grpc.v1.services.*;
import com.bestcem.xm.ticket.grpc.client.dto.qdes.QStructDTO;
import com.bestcem.xm.ticket.grpc.client.dto.qdes.QdesDTO;
import com.bestcem.xm.ticket.grpc.client.dto.qdes.QuotaDTO;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import zhongyan.xm.base.v1.Base;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;

/**
 * 倍市得 qdes 模块相关rpc接口客户端
 *
 * @author XiaoYunSong <ys.xiao@idiaoyan.com>
 * @version v1.0
 * @date 2021/8/25 14:05
 */
@Slf4j
@Service
public class TicketBaseQdesGrpcService {

    @GrpcClient(GrpcClientNames.DS_QDES)
    private BaseQdesServiceGrpc.BaseQdesServiceBlockingStub baseQdesServiceBlockingStub;


    /**
     * 获取问卷项目信息
     *
     * @param qdesId 问卷id
     * @return Survey project info
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/25 13:57
     */
    @Nullable
    public QdesDTO getQdesProject(String qdesId) {
        if (!ObjectId.isValid(qdesId)) {
            return null;
        }
        GetProjectRequest.Builder builder = GetProjectRequest.newBuilder();
        builder.setId(qdesId);
        try {
            ProjectResponse response = baseQdesServiceBlockingStub.getProject(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] QDES getSurveyProject Error; SurveyId: {} ErrorMsg: {}", qdesId, response);
                return null;
            }
            return responseToSurveyDTO(response);
        } catch (Exception e) {
            log.error("[Ticket] QDES getSurveyProject Error; SurveyId: {}", qdesId, e);
            return null;
        }
    }


    /**
     * 根据id列表批量获取问卷项目信息
     *
     * @param qdesIdList 问卷id列表咯
     * @return Survey project info list
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/24 11:52
     */
    @Nullable
    public List<QdesDTO> listQdesProjectByIds(Collection<String> qdesIdList) {
        ListProjectByIdsRequest.Builder builder = ListProjectByIdsRequest.newBuilder();
        builder.addAllIds(qdesIdList);
        try {
            ProjectSearchResponse response = baseQdesServiceBlockingStub.listProjectByIds(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] QDES listSurveyProjectByIds Error; SurveyIdList: {} ErrorMsg: {}", qdesIdList, response);
                return null;
            }
            return responseToSurveyDTOList(response);
        } catch (Exception e) {
            log.error("[Ticket] QDES listSurveyProjectByIds Error; SurveyId: {}", qdesIdList, e);
            return null;
        }
    }

    /**
     * 获取单个Quota
     *
     * @param id id
     * @return 配额DTO
     * @author <yuming.pan@idiaoyan.com>
     * @date 14:22 2021/8/31
     */
    @Nullable
    public QuotaDTO getQuota(String id) {
        GetQuotaRequest.Builder builder = GetQuotaRequest.newBuilder();
        builder.setId(id);
        try {
            QuotaResponse response = baseQdesServiceBlockingStub.getQuota(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] QDES getQuota Error; id: {} ErrorMsg: {}", id, response);
                return null;
            }
            return infoToQuotaDTO(response.getQuota());
        } catch (Exception e) {
            log.error("[Ticket] QDES getQuota Error; id: {}", id, e);
            return null;
        }
    }

    /**
     * 获取问卷所有的 QStruct
     *
     * @param id 问卷项目id
     * @return QStructDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 13:46
     */
    @Nullable
    public List<QStructDTO> ListQStruct(String id) {
        ListQStructRequest.Builder builder = ListQStructRequest.newBuilder();
        QStruct.Builder qStructBuilder = QStruct.newBuilder();
        qStructBuilder.setProjectId(id);
        builder.setQStruct(qStructBuilder);
        try {
            QStructSearchResponse response = baseQdesServiceBlockingStub.listQStruct(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] QDES getNewestQStruct Error; id: {} ErrorMsg: {}", id, response);
                return null;
            }
            return responseToQStructDTOList(response);
        } catch (Exception e) {
            log.error("[Ticket] QDES getNewestQStruct Error; id: {}", id, e);
            return null;
        }
    }


    // ========================== private model convert ==========================


    /**
     * quota to  QuotaDTO
     *
     * @param quota proto生成的Quota
     * @return 配额DTO
     * @author <yuming.pan@idiaoyan.com>
     * @date 14:24 2021/8/31
     */
    @Nullable
    private QuotaDTO infoToQuotaDTO(Quota quota) {
        if (Objects.isNull(quota)) {
            return null;
        }
        QuotaDTO quotaDTO = new QuotaDTO();
        quotaDTO.setId(quota.getId());
        quotaDTO.setName(quota.getName());
        quotaDTO.setProjectId(quota.getProjectId());
        quotaDTO.setQuotaType(quota.getQuotaTypeValue());
        quotaDTO.setQuotaCondList(quota.getQuotaCondListList());
        quotaDTO.setAvaQgidList(quota.getAvaQgidList());
        quotaDTO.setRow1(quota.getRow1());
        quotaDTO.setRow2(quota.getRow2());
        quotaDTO.setCol1(quota.getCol1());
        quotaDTO.setCol2(quota.getCol2());
        return quotaDTO;
    }


    /**
     * QStructSearchResponse to QStructDTOList
     *
     * @param response QStructSearchResponse
     * @return 按照 version 从大到小排序的 QStructDTOList
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 14:43
     */
    @Nullable
    private List<QStructDTO> responseToQStructDTOList(QStructSearchResponse response) {
        if (Objects.isNull(response)) {
            return null;
        }
        List<QStruct> infoList = response.getQStructListList();
        List<QStructDTO> dtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(infoList)) {
            for (QStruct qStruct : infoList) {
                QStructDTO dto = infoToQStructDTO(qStruct);
                if (Objects.nonNull(dto)) {
                    dtoList.add(dto);
                }
            }
        }
        dtoList.sort((a, b) -> {
            int av = Optional.ofNullable(a.getVersion()).orElse(0);
            int bv = Optional.ofNullable(b.getVersion()).orElse(0);
            return bv - av;
        });
        return dtoList;
    }


    /**
     * QStruct to QStructDTO
     *
     * @param info proto生成的 QStruct
     * @return QStructDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/11/23 14:38
     */
    @Nullable
    private QStructDTO infoToQStructDTO(QStruct info) {
        if (Objects.isNull(info)) {
            return null;
        }

        QStructDTO dto = new QStructDTO();
        dto.setId(info.getId());
        dto.setProjectId(info.getProjectId());
        dto.setVersion(info.getVersion());
        // version 没有时, 默认为0
        if (Objects.isNull(dto.getVersion())) {
            dto.setVersion(0);
        }
        dto.setReleaseDate(DateUtil.getLocalDateTime(info.getReleaseDt()));
        dto.setData(info.getData());
        dto.setWithdrawDate(DateUtil.getLocalDateTime(info.getWithdrawDt()));
        dto.setTemplates(info.getTemplates());
        dto.setAttachments(info.getAttachments());
        dto.setCsses(info.getCsses());
        dto.setGcss(info.getGcss());
        dto.setUcss(info.getUcss());
        dto.setScores(info.getScores());
        dto.setSecret(info.getSecret());
        dto.setPolicy(info.getPolicy());
        dto.setStatus(info.getStatus().getNumber());

        return dto;
    }


    /**
     * ProjectSearchResponse to SurveyDTO
     *
     * @param response ProjectSearchResponse
     * @return SurveyDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/25 14:03
     */
    @Nonnull
    private List<QdesDTO> responseToSurveyDTOList(ProjectSearchResponse response) {
        List<Project> projectList = response.getProjectListList();
        if (CollectionUtils.isEmpty(projectList)) {
            return new ArrayList<>();
        }
        List<QdesDTO> qdesDTOList = new ArrayList<>();
        for (Project project : projectList) {
            QdesDTO qdesDTO = infoToSurveyDTO(project);
            if (Objects.nonNull(qdesDTO)) {
                qdesDTOList.add(qdesDTO);
            }
        }
        return qdesDTOList;
    }

    /**
     * ProjectResponse to SurveyDTO
     *
     * @param response ProjectResponse
     * @return SurveyDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/25 13:55
     */
    @Nullable
    private QdesDTO responseToSurveyDTO(ProjectResponse response) {
        Project project = Optional.ofNullable(response).map(ProjectResponse::getProject).orElse(null);
        if (Objects.isNull(project)) {
            return null;
        }
        return infoToSurveyDTO(project);
    }

    /**
     * Project Info to SurveyDTO
     *
     * @param project Project Info
     * @return SurveyDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/25 14:00
     */
    @Nullable
    private QdesDTO infoToSurveyDTO(Project project) {
        if (Objects.isNull(project)) {
            return null;
        }
        QdesDTO qdesDTO = new QdesDTO();
        qdesDTO.setId(project.getId());
        qdesDTO.setCode(project.getCode());
        qdesDTO.setTitle(project.getTitle());
        qdesDTO.setCreator(project.getCreator());
        qdesDTO.setCompanyId(project.getCompanyId());
        qdesDTO.setGroupList(project.getGroupListList());
        qdesDTO.setVersion(project.getVersion());
        qdesDTO.setReleaseVer(project.getReleaseVer());
        qdesDTO.setStatus(project.getStatus().getNumber());
        qdesDTO.setStructId(project.getStructId());
        qdesDTO.setLogicId(project.getLogicId());
        if (!ObjectUtils.isEmpty(project.getCustomAttr())) {
            JSONValidator jsonValidator = JSONValidator.from(project.getCustomAttr());
            if (jsonValidator.validate()) {
                qdesDTO.setCustomAttr(JSON.parse(project.getCustomAttr()));
            }
        }
        qdesDTO.setSource(project.getSource());
        qdesDTO.setExtId(project.getExtId());
        qdesDTO.setTimerExpire(project.getTimerExpire());
        qdesDTO.setPType(project.getPtype().getNumber());
        qdesDTO.setIsCopyDemo(project.getIsCopyDemo());
        return qdesDTO;
    }
}
